/**
 * Bakalarska prace - Inteligentni budik
 * @package sleepCatcher
 * @file FormMgr.cpp
 * @author Jan Pesava - xpesav00
 * @email xpesav00@stud.fit.vutbr.cz
 * @date 24. 12. 2011
 */

#include <FUi.h>
#include <FUiAnimFrameAnimator.h>
#include <FUiAnimations.h>

#include "SCFormManager.h"
#include "forms/FormAlarm.h"
#include "forms/FormAlarmRepeat.h"
#include "forms/FormAlarmName.h"
#include "forms/FormAlarmAwakeType.h"
#include "forms/FormAlarmAwakeSound.h"
#include "forms/FormAlarmSet.h"
#include "forms/FormAlarmDelete.h"
#include "forms/FormCatchSleep.h"
#include "forms/FormSettings.h"
#include "forms/FormSettingsInteligentSleep.h"
#include "forms/FormSettingsSleepLength.h"
#include "forms/FormSession.h"
#include "forms/FormSessionDelete.h"
#include "forms/FormSessionInfo.h"
#include "forms/FormStatistics.h"
#include "forms/FormAlarmRing.h"

Form* SCFormManager::pCurrentForm = NULL;
HashMapT<int, Form*>* SCFormManager::pOpenForms = NULL;
Integer SCFormManager::currentFormId = 0;
bool SCFormManager::appOnBackground = false;
bool SCFormManager::screenSaver = false;

using namespace Osp::Ui::Animations;

SCFormManager::SCFormManager(void)
{
}

SCFormManager::~SCFormManager(void)
{
}

result
SCFormManager::Construct()
{
	AppLog("FormManager initializing.");

	// create form map
	pOpenForms = new HashMapT<int, Form*>();
	pOpenForms->Construct();

	// create base form
	CreateBaseForms();

	return E_SUCCESS;
}

result
SCFormManager::Destruct()
{
	// remove forms
	pOpenForms->RemoveAll();
	delete pOpenForms;

	AppLog("FormManager destructed.");

	return E_SUCCESS;
}

bool
SCFormManager::SetStarterForm(RequestId requestId, ArrayList* pArgs)
{
	if(SwitchToForm(requestId, false, pArgs, NO_SLIDE))
	{
		return true;
	} else {
		return false;
	}
}

bool
SCFormManager::SwitchToForm(RequestId requestId, bool removeCurrent = true, ArrayList* pArgs = NULL, int slideType = NO_SLIDE)
{

	Frame *pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();
	Form* pLastForm = pFrame->GetCurrentForm();
	Integer pLastFormId = currentFormId;
	Form *pForm = NULL;
	Integer *key = NULL;

	// Pokud se jedna o aktualni form.
	if(requestId == currentFormId.ToInt())
	{
		return true;
	}

	switch(requestId)
	{
		case IDF_ALARM:
		{
			key = new Integer(IDF_ALARM);
			pForm = GetForm(requestId, null);
			pFrame->SetCurrentForm(*pForm);
			((FormAlarm*)pForm)->Update();
			break;
		}
		case IDF_ALARM_SET:
		{
			key = new Integer(IDF_ALARM_SET);
			pForm = GetForm(requestId, null);
			SCAlarm* pAlarm;

			if(pArgs != NULL)
				pAlarm = static_cast<SCAlarm*>(pArgs->GetAt(0));
			else
				pAlarm = SCAlarm::GetAlarm();

			((FormAlarmSet*)pForm)->SetAlarm(pAlarm);
			((FormAlarmSet*)pForm)->Update();
			break;
		}
		case IDF_ALARM_DELETE:
		{
			key = new Integer(IDF_ALARM_DELETE);
			pForm = GetForm(requestId, null);
			pFrame->SetCurrentForm(*pForm);
			((FormAlarmDelete*)pForm)->Update();
			break;
		}
		case IDF_ALARM_NAME:
		{
			key = new Integer(IDF_ALARM_NAME);
			pForm = GetForm(requestId, null);
			((FormAlarmName*)pForm)->SetAlarm((static_cast<FormAlarmSet*>(pCurrentForm))->GetAlarm());
			pFrame->SetCurrentForm(*pForm);
			((FormAlarmName*)pForm)->Update();
			pFrame->SetCurrentForm(*pLastForm);
			break;
		}
		case IDF_ALARM_REPEAT:
		{
			key = new Integer(IDF_ALARM_REPEAT);
			pForm = GetForm(requestId, null);
			((FormAlarmRepeat*)pForm)->SetAlarm((static_cast<FormAlarmSet*>(pCurrentForm))->GetAlarm());
			((FormAlarmRepeat*)pForm)->Update();
			break;
		}
		case IDF_ALARM_AWAKE_SOUND:
		{
			key = new Integer(IDF_ALARM_AWAKE_SOUND);
			pForm = GetForm(requestId, null);
			((FormAlarmAwakeSound*)pForm)->SetAlarm((static_cast<FormAlarmSet*>(pCurrentForm))->GetAlarm());
			((FormAlarmAwakeSound*)pForm)->Update();
			break;
		}
		case IDF_ALARM_AWAKE_TYPE:
		{
			key = new Integer(IDF_ALARM_AWAKE_TYPE);
			pForm = GetForm(requestId, null);
			((FormAlarmAwakeType*)pForm)->SetAlarm((static_cast<FormAlarmSet*>(pCurrentForm))->GetAlarm());
			((FormAlarmAwakeType*)pForm)->Update();
			break;
		}
		case IDF_ALARM_RING:
		{
			key = new Integer(IDF_ALARM_RING);
			pForm = GetForm(requestId, null);
			((FormAlarmRing*)pForm)->SetAlarm(static_cast<SCAlarm*>(pArgs->GetAt(0)));
			((FormAlarmRing*)pForm)->Update();
			((FormAlarmRing*)pForm)->StartWakeUp();
			break;
		}
		case IDF_CATCH_SLEEP:
		{
			key = new Integer(IDF_CATCH_SLEEP);
			pForm = GetForm(requestId, null);
			((FormCatchSleep*)pForm)->Update();
			((FormCatchSleep*)pForm)->StartCatch();
			break;
		}
		case IDF_SETTINGS:
		{
			key = new Integer(IDF_SETTINGS);
			pForm = GetForm(requestId, null);
			((FormSettings*)pForm)->Update();
			break;
		}
		case IDF_SETTINGS_INTELLIGENT_SLEEP:
		{
			key = new Integer(IDF_SETTINGS_INTELLIGENT_SLEEP);
			pForm = GetForm(requestId, null);
			((FormSettingsInteligentSleep*)pForm)->Update();
			break;
		}
		case IDF_SETTINGS_SLEEP_LENGTH:
		{
			key = new Integer(IDF_SETTINGS_SLEEP_LENGTH);
			pForm = GetForm(requestId, null);
			((FormSettingsSleepLength*)pForm)->Update();
			break;
		}
		case IDF_SESSIONS:
		{
			key = new Integer(IDF_SESSIONS);
			pForm = GetForm(requestId, null);
			pFrame->SetCurrentForm(*pForm);
			((FormSession*)pForm)->Update();
			pFrame->SetCurrentForm(*pLastForm);
			break;
		}
		case IDF_SESSIONS_DELETE:
		{
			key = new Integer(IDF_SESSIONS_DELETE);
			pForm = GetForm(requestId, null);
			pFrame->SetCurrentForm(*pForm);
			((FormSessionDelete*)pForm)->Update();
			break;
		}
		case IDF_SESSIONS_INFO:
		{
			key = new Integer(IDF_SESSIONS_INFO);
			pForm = GetForm(requestId, null);
			((FormSessionInfo*)pForm)->SetSession(static_cast<SCSession*>(pArgs->GetAt(0)));
			((FormSessionInfo*)pForm)->Update();
			break;
		}
		case IDF_STATISTICS:
		{
			key = new Integer(IDF_STATISTICS);
			pForm = GetForm(requestId, null);
			((FormStatistics*)pForm)->Update();
			break;
		}
		default:
		{
			AppLog("Nedefinovany formular.");
			break;
		}
	}


	// Set New Form
	if(pForm != NULL)
	{
		// Delete previous form
		if(removeCurrent)
		{
			RemoveForm(pLastForm, pLastFormId, true);
		}

		pCurrentForm = pForm;
		currentFormId = key->ToInt();

		if(key != NULL)
			delete key;

		//slide form
		if(slideType != NO_SLIDE)
		{
			FrameAnimator* pAnimator = pFrame->GetFrameAnimator();
			if(pAnimator->GetStatus() == ANIMATOR_STATUS_STOPPED)
			{
				if(slideType == SLIDE_LEFT)
				{
					pAnimator->SetFormTransitionAnimation(FRAME_ANIMATOR_FORM_TRANSITION_ANIMATION_TRANSLATE_LEFT , 300, ANIMATION_INTERPOLATOR_LINEAR);
					pAnimator->SetCurrentForm(*pForm);
				} else if(slideType == SLIDE_RIGHT) {
					pAnimator->SetFormTransitionAnimation(FRAME_ANIMATOR_FORM_TRANSITION_ANIMATION_TRANSLATE_RIGHT , 300, ANIMATION_INTERPOLATOR_LINEAR);
					pAnimator->SetCurrentForm(*pForm);
				} else if(slideType == FADE_IN_OUT) {
					pAnimator->SetFormTransitionAnimation(FRAME_ANIMATOR_FORM_TRANSITION_ANIMATION_FADE_IN_OUT , 200, ANIMATION_INTERPOLATOR_LINEAR);
					pAnimator->SetCurrentForm(*pForm);
				}
			}
		} else {
			pFrame->SetCurrentForm(*pForm);
			pForm->Draw();
			pForm->Show();
		}
	} else {
		if(key != NULL)
			delete key;
		AppLog("Nepodarilo se prepnout formular.");
	}

	return true;
}

bool
SCFormManager::SlideToForm(RequestId requestId,  bool removeCurrent, Osp::Base::Collection::IList* pArgs)
{
	SwitchToForm(requestId, removeCurrent, NULL);
	return true;
}

void
SCFormManager::RemoveForm(Form* pForm, Integer formId, bool deleteForm = true)
{
	Frame *frame = Application::GetInstance()->GetAppFrame()->GetFrame();
	if(pForm != NULL)
	{
		if(frame->RemoveControl(*pForm) != E_SUCCESS)
		{
			AppLog("Formular nebyl odebran.");
		} else {
			pOpenForms->Remove(formId.ToInt());
			pForm = NULL;
		}
	}
}

void
SCFormManager::Redraw()
{
	Frame *frame = Application::GetInstance()->GetAppFrame()->GetFrame();
	Form *form = frame->GetCurrentForm();
	form->RequestRedraw(true);
}

Form*
SCFormManager::GetForm(RequestId formId, ArrayList* pArgs)
{
	// declaration
    Form* pForm = null;
    Frame *pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();
    bool isAdd = false;

    // exist form?
    pOpenForms->ContainsKey(formId, isAdd);

    if(isAdd)
    {
    	// get form list
    	pOpenForms->GetValue(formId, pForm);
    } else {
    	//create new
    	pForm = CreateForm(formId, null);

    	if(pFrame->AddControl(*pForm) != E_SUCCESS)
    	{
    		AppLog("Form isnt added to frame.");
    	}

    	pOpenForms->Add(formId, pForm);
    }

    return pForm;
}

Form*
SCFormManager::CreateForm(RequestId formId, ArrayList* pArgs)
{
	// declaration
	Form* pForm = null;

	// choose form
	switch(formId)
	{
		case IDF_ALARM:
			pForm = new FormAlarm();
			((FormAlarm*)pForm)->Initialize();
			break;
		case IDF_ALARM_SET:
			pForm = new FormAlarmSet();
			((FormAlarmSet*)pForm)->Initialize();
			break;
		case IDF_ALARM_REPEAT:
			pForm = new FormAlarmRepeat();
			((FormAlarmRepeat*)pForm)->Initialize();
			break;
		case IDF_ALARM_NAME:
			pForm = new FormAlarmName();
			((FormAlarmName*)pForm)->Initialize();
			break;
		case IDF_ALARM_AWAKE_TYPE:
			pForm = new FormAlarmAwakeType();
			((FormAlarmAwakeType*)pForm)->Initialize();
			break;
		case IDF_ALARM_AWAKE_SOUND:
			pForm = new FormAlarmAwakeSound();
			((FormAlarmAwakeSound*)pForm)->Initialize();
			break;
		case IDF_ALARM_DELETE:
			pForm = new FormAlarmDelete();
			((FormAlarmDelete*)pForm)->Initialize();
			break;
		case IDF_ALARM_RING:
			pForm = new FormAlarmRing();
			((FormAlarmRing*)pForm)->Initialize();
			break;
		case IDF_CATCH_SLEEP:
			pForm = new FormCatchSleep();
			((FormCatchSleep*)pForm)->Initialize();
			break;
		case IDF_SETTINGS:
			pForm = new FormSettings();
			((FormSettings*)pForm)->Initialize();
			break;
		case IDF_SETTINGS_INTELLIGENT_SLEEP:
			pForm = new FormSettingsInteligentSleep();
			((FormSettingsInteligentSleep*)pForm)->Initialize();
			break;
		case IDF_SETTINGS_SLEEP_LENGTH:
			pForm = new FormSettingsSleepLength();
			((FormSettingsSleepLength*)pForm)->Initialize();
			break;
		case IDF_SESSIONS:
			pForm = new FormSession();
			((FormSession*)pForm)->Initialize();
			break;
		case IDF_SESSIONS_INFO:
			pForm = new FormSessionInfo();
			((FormSessionInfo*)pForm)->Initialize();
			break;
		case IDF_SESSIONS_DELETE:
			pForm = new FormSessionDelete();
			((FormSessionDelete*)pForm)->Initialize();
			break;
		case IDF_STATISTICS:
			pForm = new FormStatistics();
			((FormStatistics*)pForm)->Initialize();
			break;
		default:
			AppLog("Neznamy formular.");
			break;
	}

	return pForm;
}

ArrayList*
SCFormManager::GetNeighboringFormsId(RequestId formId)
{
	ArrayList* pList = new ArrayList();

	if(formId == IDF_ALARM)
	{
		pList->Add(*(new Integer(IDF_ALARM_SET)));
		pList->Add(*(new Integer(IDF_ALARM_DELETE)));
		pList->Add(*(new Integer(IDF_CATCH_SLEEP)));
		pList->Add(*(new Integer(IDF_SETTINGS)));
		pList->Add(*(new Integer(IDF_SESSIONS)));
		pList->Add(*(new Integer(IDF_STATISTICS)));
	} else if(formId == IDF_SESSIONS) {
		pList->Add(*(new Integer(IDF_SESSIONS_DELETE)));
		pList->Add(*(new Integer(IDF_SESSIONS_INFO)));
		pList->Add(*(new Integer(IDF_ALARM)));
		pList->Add(*(new Integer(IDF_CATCH_SLEEP)));
		pList->Add(*(new Integer(IDF_SETTINGS)));
		pList->Add(*(new Integer(IDF_STATISTICS)));
	} else if(formId == IDF_SETTINGS) {
		pList->Add(*(new Integer(IDF_SETTINGS_INTELLIGENT_SLEEP)));
		pList->Add(*(new Integer(IDF_SETTINGS_SLEEP_LENGTH)));
		pList->Add(*(new Integer(IDF_ALARM)));
		pList->Add(*(new Integer(IDF_CATCH_SLEEP)));
		pList->Add(*(new Integer(IDF_SESSIONS)));
		pList->Add(*(new Integer(IDF_STATISTICS)));
	} else {
		AppLog("Formular nenalezen.");
	}

	return pList;
}

void
SCFormManager::CreateNeighboringForms(RequestId formId, ArrayList* pArgs)
{

}

void
SCFormManager::CreateBaseForms()
{
	//Alarm form
	if(GetForm(IDF_ALARM, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//AlarmRepeat form
	if(GetForm(IDF_ALARM_REPEAT, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//AlarmSet form
	if(GetForm(IDF_ALARM_SET, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//AlarmAwakeSound form
	if(GetForm(IDF_ALARM_AWAKE_SOUND, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//AlarmAwakeType form
	if(GetForm(IDF_ALARM_AWAKE_TYPE, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//AlarmDelete form
	if(GetForm(IDF_ALARM_DELETE, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//AlarmName form
	if(GetForm(IDF_ALARM_NAME, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//AlarmTime form
	if(GetForm(IDF_ALARM_RING, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//CathSleep form
	if(GetForm(IDF_CATCH_SLEEP, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//Settings form
	if(GetForm(IDF_SETTINGS, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//SettingsMaxAwakeTime form
	if(GetForm(IDF_SETTINGS_INTELLIGENT_SLEEP, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//SettingsSleepLength form
	if(GetForm(IDF_SETTINGS_SLEEP_LENGTH, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//Session form
	if(GetForm(IDF_SESSIONS, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//Session form
	if(GetForm(IDF_SESSIONS_DELETE, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//SessionDetail form
	if(GetForm(IDF_SESSIONS_INFO, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}

	//Statistics form
	if(GetForm(IDF_STATISTICS, null) == NULL)
	{
		AppLog("Nebyl vytvoren formular.");
	}
}

RequestId
SCFormManager::GetCurrentFormId()
{
	return currentFormId.ToInt();
}

Form*
SCFormManager::GetCurrentForm()
{
	return Application::GetInstance()->GetAppFrame()->GetFrame()->GetCurrentForm();
}

